package com.xy.mvvmdemo.bean;

import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName LiveDataBus
 * @Author xy
 * @Date 2021/7/9 14:18
 * @Description TODO
 */
public class LiveDataBus {
    private final HashMap<String, MyMutableLiveData<Object>> bus;

    private LiveDataBus() {
        bus = new HashMap<>();
    }

    private static class SingleHolder {
        private static final LiveDataBus DATA_BUS = new LiveDataBus();
    }

    public static LiveDataBus getInstance() {
        return LiveDataBus.SingleHolder.DATA_BUS;
    }


    public <T> MyMutableLiveData<T> with(String key, Class<T> type) {
        if (!bus.containsKey(key)) {
            bus.put(key, new MyMutableLiveData<Object>());
        }
        return (MyMutableLiveData<T>) bus.get(key);
    }

    public MyMutableLiveData<Object> with (String target){
        return with (target,Object.class);
    }

    public void remove(String key){
        if (bus.containsKey(key)){
            bus.remove(key);
        }
    }

    //自定义MutableLiveData
    public class MyMutableLiveData<T> extends MutableLiveData<T>{
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, observer);
            try{
                hook(observer);
            }catch (Exception e){
                e.printStackTrace();
            }
        }


        private void hook( @NonNull Observer<? super T> observer) throws Exception{
            Class<LiveData> classLiveData  = LiveData.class;
            Field fieldObserver = classLiveData.getDeclaredField("mObservers");
            fieldObserver.setAccessible(true);
            Object mObservers = fieldObserver.get(this);
            Class<?> classObservers = mObservers.getClass() ;

            Method methodGet = classObservers.getDeclaredMethod( "get",Object.class);
            methodGet.setAccessible(true);
            Object entry = methodGet.invoke(mObservers,observer);
            Object objectWrapper = ( (Map.Entry) entry).getValue( );
            Class<?> mObserver =objectWrapper.getClass().getSuperclass() ; //observer

            Field mLastVersion = mObserver.getDeclaredField( "mLastVersion");
            mLastVersion.setAccessible(true) ;
            Field mVersion = classLiveData.getDeclaredField( "mVersion") ;
            mVersion.setAccessible(true) ;
            Object mVersionValue = mVersion.get(this);
            mLastVersion.set(objectWrapper,mVersionValue) ;
            Log.d( "Av","hook: ");

        }

    }

}
